home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / DirectSound / PlaySound / playsound.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  12.6 KB  |  390 lines

  1. //----------------------------------------------------------------------------
  2. // File: PlaySound.cpp
  3. //
  4. // Desc: The PlaySound sample shows how to load and play a wave file using
  5. //       a DirectSound buffer.
  6. //
  7. // Copyright (c) Microsoft Corp. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #include "dxstdafx.h"
  10. #include <commdlg.h>
  11. #include "resource.h"
  12.  
  13.  
  14.  
  15.  
  16. //-----------------------------------------------------------------------------
  17. // Function-prototypes
  18. //-----------------------------------------------------------------------------
  19. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  20. VOID    OnInitDialog( HWND hDlg );
  21. VOID    OnOpenSoundFile( HWND hDlg );
  22. HRESULT OnPlaySound( HWND hDlg );
  23. HRESULT PlayBuffer( BOOL bLooped );
  24. VOID    OnTimer( HWND hDlg );
  25. VOID    EnablePlayUI( HWND hDlg, BOOL bEnable );
  26.  
  27.  
  28.  
  29.  
  30. //-----------------------------------------------------------------------------
  31. // Defines, constants, and global variables
  32. //-----------------------------------------------------------------------------
  33. CSoundManager* g_pSoundManager = NULL;
  34. CSound*        g_pSound = NULL;
  35. BOOL           g_bBufferPaused;
  36.  
  37.  
  38.  
  39.  
  40. //-----------------------------------------------------------------------------
  41. // Name: WinMain()
  42. // Desc: Entry point for the application.  Since we use a simple dialog for 
  43. //       user interaction we don't need to pump messages.
  44. //-----------------------------------------------------------------------------
  45. INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, 
  46.                       INT nCmdShow )
  47. {
  48.     // Display the main dialog box.
  49.     DialogBox( hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc );
  50.  
  51.     return TRUE;
  52. }
  53.  
  54.  
  55.  
  56.  
  57. //-----------------------------------------------------------------------------
  58. // Name: MainDlgProc()
  59. // Desc: Handles dialog messages
  60. //-----------------------------------------------------------------------------
  61. INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  62. {
  63.     HRESULT hr;
  64.  
  65.     switch( msg ) 
  66.     {
  67.         case WM_INITDIALOG:
  68.             OnInitDialog( hDlg );
  69.             break;
  70.  
  71.         case WM_COMMAND:
  72.             switch( LOWORD(wParam) )
  73.             {
  74.                 case IDC_SOUNDFILE:
  75.                     OnOpenSoundFile( hDlg );
  76.                     break;
  77.  
  78.                 case IDCANCEL:
  79.                     EndDialog( hDlg, IDCANCEL );
  80.                     break;
  81.  
  82.                 case IDC_PLAY:
  83.                     // The 'play'/'pause' button was pressed
  84.                     if( FAILED( hr = OnPlaySound( hDlg ) ) )
  85.                     {
  86.                         DXTRACE_ERR_MSGBOX( TEXT("OnPlaySound"), hr );
  87.                         MessageBox( hDlg, L"Error playing DirectSound buffer. "
  88.                                     L"Sample will now exit.", L"DirectSound Sample", 
  89.                                     MB_OK | MB_ICONERROR );
  90.                         EndDialog( hDlg, IDABORT );
  91.                     }
  92.                     break;
  93.  
  94.                 case IDC_STOP:
  95.                     if( g_pSound )
  96.                     {
  97.                         g_pSound->Stop();
  98.                         g_pSound->Reset();
  99.                     }
  100.  
  101.                     EnablePlayUI( hDlg, TRUE );
  102.                     break;
  103.  
  104.                 default:
  105.                     return FALSE; // Didn't handle message
  106.             }
  107.             break;
  108.  
  109.         case WM_TIMER:
  110.             OnTimer( hDlg );
  111.             break;
  112.  
  113.         case WM_DESTROY:
  114.             // Cleanup everything
  115.             KillTimer( hDlg, 1 );    
  116.             SAFE_DELETE( g_pSound );
  117.             SAFE_DELETE( g_pSoundManager );
  118.             break; 
  119.  
  120.         default:
  121.             return FALSE; // Didn't handle message
  122.     }
  123.  
  124.     return TRUE; // Handled message
  125. }
  126.  
  127.  
  128.  
  129.  
  130. //-----------------------------------------------------------------------------
  131. // Name: OnInitDialog()
  132. // Desc: Initializes the dialogs (sets up UI controls, etc.)
  133. //-----------------------------------------------------------------------------
  134. VOID OnInitDialog( HWND hDlg )
  135. {
  136.     HRESULT hr;
  137.  
  138.     // Load the icon
  139. #ifdef _WIN64
  140.     HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  141. #else
  142.     HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  143. #endif
  144.     HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDR_MAINFRAME ) );
  145.  
  146.     // Set the icon for this dialog.
  147.     SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  148.     SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  149.  
  150.     // Create a static IDirectSound in the CSound class.  
  151.     // Set coop level to DSSCL_PRIORITY, and set primary buffer 
  152.     // format to stereo, 22kHz and 16-bit output.
  153.     g_pSoundManager = new CSoundManager();
  154.     if( NULL == g_pSoundManager )
  155.     {
  156.         DXTRACE_ERR_MSGBOX( TEXT("Initialize"), E_OUTOFMEMORY );
  157.         EndDialog( hDlg, IDABORT );
  158.         return;
  159.     }
  160.  
  161.     if( FAILED( hr = g_pSoundManager->Initialize( hDlg, DSSCL_PRIORITY ) ) )
  162.     {
  163.         DXTRACE_ERR_MSGBOX( TEXT("Initialize"), hr );
  164.         MessageBox( hDlg, L"Error initializing DirectSound.  Sample will now exit.", 
  165.                           L"DirectSound Sample", MB_OK | MB_ICONERROR );
  166.         EndDialog( hDlg, IDABORT );
  167.         return;
  168.     }
  169.     
  170.     if( FAILED( hr = g_pSoundManager->SetPrimaryBufferFormat( 2, 22050, 16 ) ) )
  171.     {
  172.         DXTRACE_ERR_MSGBOX( TEXT("SetPrimaryBufferFormat"), hr );
  173.         MessageBox( hDlg, L"Error initializing DirectSound.  Sample will now exit.", 
  174.                           L"DirectSound Sample", MB_OK | MB_ICONERROR );
  175.         EndDialog( hDlg, IDABORT );
  176.         return;
  177.     }
  178.  
  179.     g_bBufferPaused = FALSE;
  180.  
  181.     // Create a timer, so we can check for when the soundbuffer is stopped
  182.     SetTimer( hDlg, 0, 250, NULL );
  183.  
  184.     // Set the UI controls
  185.     SetDlgItemText( hDlg, IDC_FILENAME, TEXT("No file loaded.") );
  186. }
  187.  
  188.  
  189.  
  190.  
  191. //-----------------------------------------------------------------------------
  192. // Name: OnOpenSoundFile()
  193. // Desc: Called when the user requests to open a sound file
  194. //-----------------------------------------------------------------------------
  195. VOID OnOpenSoundFile( HWND hDlg ) 
  196. {
  197.     HRESULT hr;
  198.  
  199.     static TCHAR strFileName[MAX_PATH] = TEXT("");
  200.     static TCHAR strPath[MAX_PATH] = TEXT("");
  201.  
  202.     // Setup the OPENFILENAME structure
  203.     OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL,
  204.                          TEXT("Wave Files\0*.wav\0All Files\0*.*\0\0"), NULL,
  205.                          0, 1, strFileName, MAX_PATH, NULL, 0, strPath,
  206.                          TEXT("Open Sound File"),
  207.                          OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0,
  208.                          TEXT(".wav"), 0, NULL, NULL };
  209.  
  210.     // Get the default media path (something like C:\WINDOWS\MEDIA)
  211.     if( '\0' == strPath[0] )
  212.     {
  213.         if( GetWindowsDirectory( strPath, MAX_PATH ) != 0 )
  214.         {
  215.             if( wcscmp( &strPath[wcslen(strPath)], TEXT("\\") ) )
  216.                 wcscat( strPath, TEXT("\\") );
  217.             wcscat( strPath, TEXT("MEDIA") );
  218.         }
  219.     }
  220.  
  221.     if( g_pSound )
  222.     {
  223.         g_pSound->Stop();
  224.         g_pSound->Reset();
  225.     }
  226.  
  227.     // Update the UI controls to show the sound as loading a file
  228.     EnableWindow(  GetDlgItem( hDlg, IDC_PLAY ), FALSE);
  229.     EnableWindow(  GetDlgItem( hDlg, IDC_STOP ), FALSE);
  230.     SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Loading file...") );
  231.  
  232.     // Display the OpenFileName dialog. Then, try to load the specified file
  233.     if( TRUE != GetOpenFileName( &ofn ) )
  234.     {
  235.         SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Load aborted.") );
  236.         return;
  237.     }
  238.  
  239.     SetDlgItemText( hDlg, IDC_FILENAME, TEXT("") );
  240.  
  241.     // Free any previous sound, and make a new one
  242.     SAFE_DELETE( g_pSound );
  243.  
  244.     // Verify the file is small
  245.     HANDLE hFile = CreateFile( strFileName, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
  246.     if( hFile != NULL )
  247.     {
  248.         // If you try to open a 100MB wav file, you could run out of system memory with this
  249.         // sample cause it puts all of it into a large buffer.  If you need to do this, then 
  250.         // see the "StreamData" sample to stream the data from the file into a sound buffer.
  251.         DWORD dwFileSizeHigh = 0;
  252.         DWORD dwFileSize = GetFileSize( hFile, &dwFileSizeHigh );
  253.         CloseHandle( hFile );
  254.  
  255.         if( dwFileSizeHigh != 0 || dwFileSize > 1000000 )
  256.         {
  257.             SetDlgItemText( hDlg, IDC_FILENAME, TEXT("File too large.  You should stream large files.") );
  258.             return;
  259.         }
  260.     }
  261.  
  262.     // Load the wave file into a DirectSound buffer
  263.     if( FAILED( hr = g_pSoundManager->Create( &g_pSound, strFileName, 0, GUID_NULL ) ) )
  264.     {
  265.         // Not a critical failure, so just update the status
  266.         DXTRACE_ERR( TEXT("Create"), hr );
  267.         SetDlgItemText( hDlg, IDC_FILENAME, TEXT("Could not create sound buffer.") );
  268.         return; 
  269.     }
  270.  
  271.     // Update the UI controls to show the sound as the file is loaded
  272.     SetDlgItemText( hDlg, IDC_FILENAME, strFileName );
  273.     EnablePlayUI( hDlg, TRUE );
  274.  
  275.     // Remember the path for next time
  276.     wcscpy( strPath, strFileName );
  277.     WCHAR* strLastSlash = wcsrchr( strPath, '\\' );
  278.     if( strLastSlash )
  279.         strLastSlash[0] = '\0';
  280. }
  281.  
  282.  
  283.  
  284.  
  285. //-----------------------------------------------------------------------------
  286. // Name: OnPlaySound()
  287. // Desc: User hit the "Play" button
  288. //-----------------------------------------------------------------------------
  289. HRESULT OnPlaySound( HWND hDlg ) 
  290. {
  291.     HRESULT hr;
  292.  
  293.     HWND hLoopButton = GetDlgItem( hDlg, IDC_LOOP_CHECK );
  294.     BOOL bLooped = ( SendMessage( hLoopButton, BM_GETSTATE, 0, 0 ) == BST_CHECKED );
  295.  
  296.     if( g_bBufferPaused )
  297.     {
  298.         // Play the buffer since it is currently paused
  299.         DWORD dwFlags = bLooped ? DSBPLAY_LOOPING : 0L;
  300.         if( FAILED( hr = g_pSound->Play( 0, dwFlags ) ) )
  301.             return DXTRACE_ERR( TEXT("Play"), hr );
  302.  
  303.         // Update the UI controls to show the sound as playing
  304.         g_bBufferPaused = FALSE;
  305.         EnablePlayUI( hDlg, FALSE );
  306.     }
  307.     else
  308.     {
  309.         if( g_pSound->IsSoundPlaying() )
  310.         {
  311.             // To pause, just stop the buffer, but don't reset the position
  312.             if( g_pSound )
  313.                 g_pSound->Stop();
  314.  
  315.             g_bBufferPaused = TRUE;
  316.             SetDlgItemText( hDlg, IDC_PLAY, L"Play" );
  317.         }
  318.         else
  319.         {
  320.             // The buffer is not playing, so play it again
  321.             DWORD dwFlags = bLooped ? DSBPLAY_LOOPING : 0L;
  322.             if( FAILED( hr = g_pSound->Play( 0, dwFlags ) ) )
  323.                 return DXTRACE_ERR( TEXT("Play"), hr );
  324.  
  325.             // Update the UI controls to show the sound as playing
  326.             g_bBufferPaused = FALSE;
  327.             EnablePlayUI( hDlg, FALSE );
  328.         }
  329.     }
  330.  
  331.     return S_OK;
  332. }
  333.  
  334.  
  335.  
  336.  
  337. //-----------------------------------------------------------------------------
  338. // Name: OnTimer()
  339. // Desc: When we think the sound is playing this periodically checks to see if 
  340. //       the sound has stopped.  If it has then updates the dialog.
  341. //-----------------------------------------------------------------------------
  342. VOID OnTimer( HWND hDlg ) 
  343. {
  344.     if( IsWindowEnabled( GetDlgItem( hDlg, IDC_STOP ) ) )
  345.     {
  346.         // We think the sound is playing, so see if it has stopped yet.
  347.         if( !g_pSound->IsSoundPlaying() ) 
  348.         {
  349.             // Update the UI controls to show the sound as stopped
  350.             EnablePlayUI( hDlg, TRUE );
  351.         }
  352.     }
  353. }
  354.  
  355.  
  356.  
  357.  
  358. //-----------------------------------------------------------------------------
  359. // Name: EnablePlayUI( hDlg,)
  360. // Desc: Enables or disables the Play UI controls 
  361. //-----------------------------------------------------------------------------
  362. VOID EnablePlayUI( HWND hDlg, BOOL bEnable )
  363. {
  364.     if( bEnable )
  365.     {
  366.         EnableWindow(   GetDlgItem( hDlg, IDC_LOOP_CHECK ), TRUE );
  367.         EnableWindow(   GetDlgItem( hDlg, IDC_STOP ),       FALSE );
  368.  
  369.         EnableWindow(   GetDlgItem( hDlg, IDC_PLAY ),       TRUE );
  370.         SetFocus(       GetDlgItem( hDlg, IDC_PLAY ) );
  371.         SetDlgItemText( hDlg, IDC_PLAY, L"&Play" );
  372.     }
  373.     else
  374.     {
  375.         EnableWindow(  GetDlgItem( hDlg, IDC_LOOP_CHECK ), FALSE );
  376.         EnableWindow(  GetDlgItem( hDlg, IDC_STOP ),       TRUE );
  377.         SetFocus(      GetDlgItem( hDlg, IDC_STOP ) );
  378.  
  379.         EnableWindow(  GetDlgItem( hDlg, IDC_PLAY ),       TRUE );
  380.         SetDlgItemText( hDlg, IDC_PLAY, L"&Pause" );
  381.     }
  382. }
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.